const { reject, values } = require('lodash');
const MyPromise = require('./MyPromise');
/*创建promise时执行器会立即执行;
  当做promise执行器中遇到setTimeout异步代码时;
  不等待异步代码之后后再执行，而是会立即执行;
  mypromise.then()会马上执行;
  但是此时mypromise类中没有promise状态为pending时可执行的方法。
*/
// let mypromise = new MyPromise((resolve, reject) => {
//     setTimeout(() => {
//         resolve('成功');
//     }, 2000);
// });
// mypromise.then(
//     value => {
//         console.log(value);
//     },
//     reason => console.log(reason)
// );

/**
  三、then()方法多次调用
  同一个promise对象可以多次调用then，每次调用then时，then中的回调函数都需要执行
  两种情况：
  1.同步：调用then时promise状态已知，是成功或失败
  2.异步：如果调用then时promise状态未知，那么需要将每个then中回调方法都保存起来，再等待异步结束后再去执行每个对应的回调函数
    因为这里需要保存多个then中的多个回调函数，需将MyPromise保存回调函数的successCallback和failCallbck更改为可保存多个函数的数组

*/
// let mypromise = new MyPromise((resolve, reject) => {
//     resolve('成功');
//     reject('失败');
// });
// mypromise.then(
//     value => console.log(value),
//     reason => console.log(reason)
// );
// mypromise.then(
//     value => console.log(value),
//     reason => console.log(reason)
// );
// mypromise.then(
//     value => console.log(value),
//     reason => console.log(reason)
// );

/**
  四、then()方法链式调用
  后面then()方法拿到的值时上一个then()回调函数的返回值，then中return 值，则后面then的值为上一个return返回的值
  1.实现then()链式调用，之所以可以链式调用的根本在于then每次返回的为promise对象，为了实现可以链式调用，MyPromise中需要在每次then中返回promise对象
  2.如何将上一个then的返回值放入后面then方法中？
    then中回调要么是成功，要么是失败，先从成功入手，比如上一个then是成功，那么then的返回值就是成功函数的返回值。

*/
// let mypromise = new MyPromise((resolve, reject) => {
//     resolve('成功');
//     reject('失败');
// });
// mypromise
//     .then(
//         value => {
//             console.log(value);
//             return 10;
//         },
//         reason => console.log(reason)
//     )
//     .then(value => {
//         console.log(value);
//         return 1000;
//     })
//     .then(value => console.log(value));
/**
  五、then()方法链式调用
  后面then()方法拿到的值时上一个then()回调函数的返回值
  then中返回的是一个新的promise对象 
  1.查看返回的promise对象状态
    如果promise状态是成功，通过resolve将promise的成功结果传递给下一个promise对象；
    如果promise状态是失败，通过reject将promise的失败结果传递给下一个promise对象；
  2.在上面第四步中存储的let x = successCallback(this.value);回调的值时需要判断，如果是普通值则直接指向resolve，如果是promise对象需判断对象状态
  3.因为这个函数需要考虑同步、异步时的情况，所以单独写个函数
*/
// let mypromise = new MyPromise((resolve, reject) => {
//     resolve('成功');
//     reject('失败');
// });
// function other() {
//     return new MyPromise((resolve, reject) => {
//         resolve(200);
//     });
// }
// mypromise
//     .then(
//         value => {
//             console.log(value);
//             return other();
//         },
//         reason => console.log(reason)
//     )
//     .then(value => {
//         console.log(value);
//         return 1000;
//     })
//     .then(value => console.log(value));
/**
  五、then()方法链式调用
  then()方法中可返回的是一个新的promise对象，then()方法回调中不能返回 当前then方法所返回的promise对象;
  例如下方例子，每个promise的then方法返回的都是一个新的promise，我们把then返回的promise存到p2中，然后在then中return p2.
  此时会报错 (node:20948) UnhandledPromiseRejectionWarning: TypeError: Chaining cycle detected for promise #<Promise>
  提示“循环调用promise”
  解决这个问题，需在then方法回调中判断返回的是不是原有的promise对象，如果是则只需reject对象
*/
// let p1 = new Promise((resolve, reject) => {
//     resolve(1);
// });
// let p2 = p1.then(value => {
//     console.log(value);
//     return p2;
// });

// let mypromise = new MyPromise((resolve, reject) => {
//     resolve('成功');
//     reject('失败');
// });
// let p1 = mypromise.then(value => {
//     console.log(value);
//     return p1;
// });
// p1.then(
//     value => {
//         console.log(value);
//     },
//     reason => console.log(reason)
// );

/**
  六、错误处理
  错误情形一：执行器当中代码执行时发生错误时，就让promise状态更改为rejected。将状态改为rejected后，then方法内第二个回调中可以捕获这个错误。
  错误情形二：then回调中执行时发生错误，这个错误要在下一个then中捕获到。
 */
let promise = new MyPromise((resolve, reject) => {
    // resolve('成功');
    setTimeout(() => {
        resolve('成功');
    }, 2000);
    // reject('失败');
    // throw new Error('mistake');
});
// promise
//     .then(
//         value => {
//             console.log(value);
//             return '123';
//             // throw new Error('then error');
//         },
//         reason => {
//             console.log(reason);
//             return 2000;
//         }
//     )
//     .then(value => console.log(value));

/**
 * 七、then中传递参数处理
   then()中参数为可选的，可传递2个、1个或者1个也不传，当1个值不传时是如何向后传递值得呢？
   实现原理：当then()中什么也没有传递时，相当于then(value=>value),单纯的将value向后传递但没有执行任何操作。
   在mypromise我们可以添加这样的操作
 */

/**
 * 9、promise.all()方法
 处理异步并发问题，允许程序按照异步代码调用的顺序得到异步代码的结果。
 promise.all()语法分析：
 1.接收数组。数组中可为任何值，包括普通值和promise对象。
 2.promise.all()结果的值一定是数组执行顺序的值
 3.promise.all()的返回值为promise对象，可以在其后链式调用then方法

 特点：
 数组中所有的结果是成功的，则返回的promise对象结果是成功的，如果有一个失败，那么返回的promise结果是失败。

 实现思路：
 promise.all()，通过点调用，所以它是静态方法

*/
// function p9() {
//     return new MyPromise(function (resolve, reject) {
//         setTimeout(() => {
//             resolve('p9');
//         }, 2000);
//     });
// }
// function p10() {
//     return new MyPromise(function (resolve, reject) {
//         resolve('p10');
//     });
// }
// MyPromise.all(['a', 'b', p9(), p10(), 'c']).then(function (result) {
//     // result=>'a', 'b', p9, p10, 'c'
//     console.log(result);
// });
/**
 10.promise.resolve()
 将给定的值转为promise对象，promise.resolve()返回一个promise对象，在返回的promise对象中把给定的值包到promise对象中 
 内部判断，如果是promise则直接返回传入的promise
 */

/**
 11.promise.finally()
 无论promise最后的状态是成功或者失败，finally中方法都会执行；
 promise.finally()后可链式调用then()拿到当前promise对象返回的结果；
 

 实现原理：
 finally不是静态方法，需定义到MyPromise原型上

 finally中可以return一个新的promise
 */

/**
 12.promise.catch()
处理当前promise状态为失败情况，当调用then方法时没有传入失败回调，那失败回调会被catch方法捕获，去执行catch中的回调函数
 */
function p12() {
    return new MyPromise(function (resolve, reject) {
        // resolve('成功');
        reject('失败');
    });
}
p12()
    .then(value => console.log(value))
    .catch(reason => console.log(reason));
